// POJ 3585 Accumulation Degree
// 二次扫描，换根
// 陈锋
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>

/*
记D(x)为以x为根的子树中，以x为源点从x发出的最大流量，则：
D(x)=∑ Deg(y)==1?(x,y):min⁡(D(y),c(x,y)), y∈son(x)
任选x=1作为树根，DFS一次，计算所有的D(u)
记F(u)为u作为根到叶节点的最大流量。以1为根，则显然F(1)=D(1)。
对于y，记x=pa(y)，如果Degree(x)=1，则F(y)=D(y)+c(x,y)
否则，从y流出的流量，就是D(y)+y→x→w。
x→y的部分为min(D(y), c(x,y))
那么x→w就是F(x)- min(D(y), c(x,y))
F(y)=D(y)+min(c(x,y), F(x)-min(D(y), c(x,y)))
*/
using namespace std;

const int MAXN = 2e5 + 4;
int N, F[MAXN], D[MAXN];
struct Edge {
  int v, w;
  Edge(int to = 0, int _w = 0) : v(to), w(_w) {}
};
vector<Edge> G[MAXN];
int dfs1(int u, int fa) {
  int& d = D[u];
  d = 0;
  for (size_t i = 0; i < G[u].size(); i++) {
    const Edge& e = G[u][i];
    if (e.v == fa) continue;
    int c = e.w;
    if (G[e.v].size() > 1) c = min(c, dfs1(e.v, u));
    d += c;
  }
  return d;
}

void dfs2(int u, int fa) {
  for (size_t i = 0; i < G[u].size(); i++) {
    const Edge& e = G[u][i];
    if (e.v == fa) continue;
    if (G[u].size() == 1)
      F[e.v] = D[e.v] + e.w;
    else
      F[e.v] = D[e.v] + min(e.w, F[u] - min(D[e.v], e.w));
    dfs2(e.v, u);
  }
}

int main() {
  int T;
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &N);
    fill_n(D, N + 1, 0);
    for (int i = 0; i <= N; i++) G[i].clear();
    for (int i = 1, x, y, z; i < N; i++) {
      scanf("%d%d%d", &x, &y, &z);
      G[x].push_back(Edge(y, z)), G[y].push_back(Edge(x, z));
    }
    dfs1(1, -1);
    F[1] = D[1];
    dfs2(1, -1);
    int ans = *max_element(F + 1, F + N + 1);
    printf("%d\n", ans);
  }
  return 0;
}
// Accepted 1282ms 22452kB 1272 G++ 2020-12-08 20:55:24 22197138